
package com.hlkj.pay.app.merchant.ext.impl.wxpay;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSONArray;
import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.util.id.IdUtils;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.framework.extension.annotation.Extension;
import com.hlkj.pay.app.merchant.ext.ChannelMerchantAccessExtPt;
import com.hlkj.pay.app.merchant.ext.MerchantExtConstant;
import com.hlkj.pay.app.merchant.ext.dto.access.*;
import com.hlkj.pay.app.merchant.ext.impl.fuyou.utils.FuYouCallBackParamsParseUtil;
import com.hlkj.pay.app.merchant.ext.impl.wxpay.constant.ContactType;
import com.hlkj.pay.app.merchant.ext.impl.wxpay.constant.IdDocType;
import com.hlkj.pay.app.merchant.ext.impl.wxpay.constant.WxPayExtConstant;
import com.hlkj.pay.app.merchant.ext.impl.wxpay.dto.WxAppChannelParams;
import com.hlkj.pay.app.merchant.ext.impl.wxpay.dto.WxPayAccessQueryResp;
import com.hlkj.pay.app.merchant.ext.impl.wxpay.dto.WxPayConfig;
import com.hlkj.pay.app.merchant.ext.impl.wxpay.handler.WxPayCommonParamsHandle;
import com.hlkj.pay.dto.merchant.AccessChannelParamsDto;
import com.hlkj.pay.dto.merchant.MerchantAccessDto;
import com.hlkj.pay.dto.merchant.MerchantAccessSignLink;
import com.hlkj.pay.enums.CommonEnum;
import com.hlkj.pay.enums.MerchantEnum;
import com.hlkj.pay.enums.PayEnums;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAccessCardDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAccessCertInfoDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAccessInfoDO;
import com.hlkj.pay.infrastructure.model.pay.PayChannelDictDO;
import com.hlkj.pay.infrastructure.model.pay.PayChannelRequestDO;
import com.hlkj.pay.infrastructure.model.pay.ProviderChannelConfigDO;
import com.hlkj.pay.service.pay.IPayChannelDictService;
import com.hlkj.pay.vo.order.resp.MerchantProductQueryResp;
import com.ijpay.core.IJPayHttpResponse;
import com.ijpay.core.enums.AuthTypeEnum;
import com.ijpay.core.enums.RequestMethodEnum;
import com.ijpay.core.kit.PayKit;
import com.ijpay.core.kit.RsaKit;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.enums.WxDomainEnum;
import com.ijpay.wxpay.enums.v3.Apply4SubApiEnum;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 微信进件操作
 */
@Slf4j
@Repository
@RequiredArgsConstructor
@Extension(bizId = MerchantExtConstant.CHANNEL_WX_PAY)
public class WxMerchantAccessExtPt implements ChannelMerchantAccessExtPt {

    private final WxPayCommonParamsHandle wxPayCommonParamsHandle;

    private final IPayChannelDictService payChannelDictService;

    @Override
    public void channelConfigCheck(ChannelMerchantAccessCommonContext channelMerchantAccessCommonContext) {
    }

    @Override
    public void merchantAccess(ChannelMerchantAccessContext channelMerchantAccessContext) {
        log.info("微信渠道提交进件 请求参数:{}", JsonUtils.toJsonString(channelMerchantAccessContext));
        CommonResult<WxPayConfig> wxPayConfigCommonResult = wxPayCommonParamsHandle.wxPayConfig(channelMerchantAccessContext.getProviderChannelConfig(),
                channelMerchantAccessContext.isTest());
        if (!wxPayConfigCommonResult.isSuccess()) {
            channelMerchantAccessContext.setRemark(wxPayConfigCommonResult.getMsg());
            channelMerchantAccessContext.setProcessStatus(false);
            return;
        }
        MerchantAccessDto merchantAccessDto = channelMerchantAccessContext.getMerchantAccessDto();
        MerchantAccessInfoDO merchantAccessInfo = merchantAccessDto.getMerchantAccessInfo();
        if (StringUtils.hasText(merchantAccessInfo.getSubMchId())) {
            log.info("微信渠道当前没有更新商户信息直接返回:{}", merchantAccessInfo.getSubMchId());
            return;
        }
        // 主体是否企业
        boolean enterprise = MerchantEnum.MERCHANT_TYPE.COMPANY.getCode() == merchantAccessInfo.getType() ? true : false;
        // 结算卡信息
        MerchantAccessCardDO merchantAccessCard = merchantAccessDto.getMerchantAccessCard();
        // 进件请求记录
        PayChannelRequestDO payChannelRequestDO = new PayChannelRequestDO();
        channelMerchantAccessContext.setPayChannelRequestDO(payChannelRequestDO);
        try {
            // 初始化微信配置
            WxPayConfig wxPayConfig = wxPayConfigCommonResult.getData();
            // 支付公钥 敏感信息加密
            PublicKey publicKey = RsaKit.loadPublicKey(PayKit.getPublicKeyByContent(PayKit.getCertFileContent(wxPayConfig.getPayPublicPath())));
            // 拼装接口
            Map<String,Object> reqBody = new HashMap<>();
            // 业务申请编号
            reqBody.put("business_code", IdUtils.getSnowflakeNextIdStr());
            // 超级管理员信息
            Map<String,Object> contactInfo = new HashMap<>();
            // 判断法人是否是联系人
            if(!CommonEnum.YES_NO_TYPE.YES.getCode().equals(merchantAccessInfo.getContactType() )){
                // 经营场景类的其他的文件 第一个文件是否上传(业务办理授权函)
                List<String> fileUrls = merchantAccessDto.getMerchantAccessBusiness().getFileUrls();
                if(CollUtil.isEmpty(fileUrls)){
                    // 直接结束
                    channelMerchantAccessContext.setRemark("业务办理授权函未上传");
                    channelMerchantAccessContext.setProcessStatus(false);
                    return;
                }
                // 判断是经办人时 需补充以下数据
                contactInfo.put("contact_type", ContactType.SUPER.name());
                contactInfo.put("contact_name",  wxPayCommonParamsHandle.rsaEncryptOAEP(merchantAccessDto.getMerchantAccessContact().getName(),publicKey));
                contactInfo.put("mobile_phone",  wxPayCommonParamsHandle.rsaEncryptOAEP(merchantAccessDto.getMerchantAccessContact().getPhone(),publicKey));
                contactInfo.put("contact_email",  wxPayCommonParamsHandle.rsaEncryptOAEP(merchantAccessDto.getMerchantAccessContact().getOtherValue(),publicKey));
                contactInfo.put("contact_id_doc_type", IdDocType.IDENTIFICATION_TYPE_IDCARD.name());
                contactInfo.put("contact_id_number",  wxPayCommonParamsHandle.rsaEncryptOAEP(merchantAccessDto.getMerchantAccessContact().getCertNo(),publicKey));
                contactInfo.put("contact_id_doc_copy", wxPayCommonParamsHandle.getV3UploadFileMediaId(merchantAccessDto.getMerchantAccessContact().getCertFrontUrl(),wxPayConfig));
                contactInfo.put("contact_id_doc_copy_back", wxPayCommonParamsHandle.getV3UploadFileMediaId(merchantAccessDto.getMerchantAccessContact().getCertBackUrl(),wxPayConfig));
                contactInfo.put("business_authorization_letter", wxPayCommonParamsHandle.getV3UploadFileMediaId(fileUrls.get(0),wxPayConfig));

                contactInfo.put("contact_period_begin",merchantAccessDto.getMerchantAccessContact().getCertBeginDate());
                if(merchantAccessDto.getMerchantAccessContact().getCertValidityType() == 1){
                    contactInfo.put("contact_period_end","长期");
                }else{
                    contactInfo.put("contact_period_end",merchantAccessDto.getMerchantAccessContact().getCertEndDate());
                }
            }else{
                contactInfo.put("contact_type",ContactType.LEGAL.name());
                contactInfo.put("contact_name",  wxPayCommonParamsHandle.rsaEncryptOAEP(merchantAccessDto.getMerchantAccessLegal().getName(),publicKey));
                contactInfo.put("mobile_phone",  wxPayCommonParamsHandle.rsaEncryptOAEP(merchantAccessDto.getMerchantAccessLegal().getPhone(),publicKey));
                contactInfo.put("contact_email",  wxPayCommonParamsHandle.rsaEncryptOAEP(merchantAccessDto.getMerchantAccessLegal().getOtherValue(),publicKey));
            }

            reqBody.put("contact_info",contactInfo);

            // 主体资料
            Map<String,Object> subjectInfo = new HashMap<>();
            subjectInfo.put("subject_type", WxPayCommonParamsHandle.companyType(Integer.valueOf(merchantAccessDto.getMerchantAccessLicense().getCompanyType())));
            // 主体资料 -> 营业执照信息
            Map<String,Object> businessLicenseInfo = new HashMap<>();
            businessLicenseInfo.put("license_copy", wxPayCommonParamsHandle.getV3UploadFileMediaId(merchantAccessDto.getMerchantAccessLicense().getLicenseUrl(),wxPayConfig));
            businessLicenseInfo.put("license_number",merchantAccessDto.getMerchantAccessLicense().getLicenseCode());
            businessLicenseInfo.put("merchant_name",merchantAccessDto.getMerchantAccessLicense().getName());
            businessLicenseInfo.put("legal_person",merchantAccessDto.getMerchantAccessLegal().getName());
            businessLicenseInfo.put("license_address",merchantAccessDto.getMerchantAccessLicense().getAddress());
            businessLicenseInfo.put("period_begin",merchantAccessDto.getMerchantAccessLicense().getLicenseBeginDate());
            if(merchantAccessDto.getMerchantAccessLicense().getLicenseValidityType() == 1){
                businessLicenseInfo.put("period_end","长期");
            }else{
                businessLicenseInfo.put("period_end",merchantAccessDto.getMerchantAccessLicense().getLicenseEndDate());
            }
            subjectInfo.put("business_license_info",businessLicenseInfo);

            //经营者/法人身份证件
            Map<String,Object> identityInfo = new HashMap<>();
            identityInfo.put("id_holder_type",ContactType.LEGAL.name());
            identityInfo.put("id_doc_type",IdDocType.IDENTIFICATION_TYPE_IDCARD.name());
            Map<String,Object> idCardInfo = new HashMap<>();
            idCardInfo.put("id_card_copy", wxPayCommonParamsHandle.getV3UploadFileMediaId(merchantAccessDto.getMerchantAccessLegal().getCertFrontUrl(),wxPayConfig));
            idCardInfo.put("id_doc_type", wxPayCommonParamsHandle.certType(merchantAccessDto.getMerchantAccessLegal().getCertType()));
            idCardInfo.put("id_card_national", wxPayCommonParamsHandle.getV3UploadFileMediaId(merchantAccessDto.getMerchantAccessLegal().getCertBackUrl(),wxPayConfig));
            idCardInfo.put("id_card_name",  wxPayCommonParamsHandle.rsaEncryptOAEP(merchantAccessDto.getMerchantAccessLegal().getName(),publicKey));
            idCardInfo.put("id_card_number",  wxPayCommonParamsHandle.rsaEncryptOAEP(merchantAccessDto.getMerchantAccessLegal().getCertNo(),publicKey));
            idCardInfo.put("id_card_address",  wxPayCommonParamsHandle.rsaEncryptOAEP(merchantAccessDto.getMerchantAccessLegal().getAddress(),publicKey));

            idCardInfo.put("card_period_begin",merchantAccessDto.getMerchantAccessLegal().getCertBeginDate());
            if(merchantAccessDto.getMerchantAccessLegal().getCertValidityType() == 1){
                idCardInfo.put("card_period_end","长期");
            }else{
                idCardInfo.put("card_period_end",merchantAccessDto.getMerchantAccessLegal().getCertEndDate());
            }
            identityInfo.put("id_card_info",idCardInfo);

             // 1、若经营者/法人是最终受益人，则填写：true。
             // 2、若经营者/法人不是最终受益人，则填写：false。
            if(enterprise){
                identityInfo.put("owner",true);
            }
            subjectInfo.put("identity_info",identityInfo);

            //最终受益人信息列表(UBO)】 仅企业需要填写
            if(enterprise && CollUtil.isNotEmpty(merchantAccessDto.getMerchantAccessBenefitList())){
                subjectInfo.put("ubo_info_list",getUnoArray(merchantAccessDto.getMerchantAccessBenefitList(),wxPayConfig,publicKey));
            }

            reqBody.put("subject_info",subjectInfo);

            // 商家经营资料
            Map<String,Object> businessInfo = new HashMap<>();
            businessInfo.put("merchant_shortname",merchantAccessDto.getMerchantAccessBusiness().getShortName());
            businessInfo.put("service_phone",merchantAccessDto.getMerchantAccessBusiness().getServicePhone());

            // 商家经营资料 -> 经营场景  ARR先默认线下场景
            Map<String,Object> salesInfo = new HashMap<>();
             // 线下场景支付
            salesInfo.put("sales_scenes_type",CollUtil.newArrayList("SALES_SCENES_STORE"));
            Map<String,Object> bizStoreInfo = new HashMap<>();
            bizStoreInfo.put("biz_store_name",merchantAccessDto.getMerchantAccessBusiness().getShortName());
            bizStoreInfo.put("biz_address_code",merchantAccessDto.getMerchantAccessBusiness().getAreaCode());
            bizStoreInfo.put("biz_store_address",merchantAccessDto.getMerchantAccessBusiness().getAddress());
            bizStoreInfo.put("store_entrance_pic",CollUtil.newArrayList(wxPayCommonParamsHandle.getV3UploadFileMediaId(merchantAccessDto.getMerchantAccessBusiness().getStoreHeaderUrl(),wxPayConfig)));
            bizStoreInfo.put("indoor_pic",CollUtil.newArrayList(wxPayCommonParamsHandle.getV3UploadFileMediaId(merchantAccessDto.getMerchantAccessBusiness().getStoreIndoorUrl(),wxPayConfig)));
            salesInfo.put("biz_store_info",bizStoreInfo);
            businessInfo.put("sales_info",salesInfo);

            reqBody.put("business_info",businessInfo);

            // 商家结算信息
            Map<String,Object> settlementInfo = new HashMap<>();
            // settlement_id 取前三位
            String mcc = merchantAccessDto.getMerchantAccessBusiness().getMcc();
            settlementInfo.put("settlement_id",mcc.substring(0,3));
            settlementInfo.put("qualification_type",mcc.substring(3,mcc.length()));
            reqBody.put("settlement_info",settlementInfo);

            // 银行信息
            Map<String,Object> bankAccountInfo = new HashMap<>();
            // 账号类型 0：对公账户 1：对私法人账户 2：对私非法人账户
            MerchantEnum.CARD_TYPE cardType = MerchantEnum.CARD_TYPE.from(merchantAccessCard.getType());
            switch (cardType) {
                case CORPORATE_ACCOUNT:
                    bankAccountInfo.put("bank_account_type","BANK_ACCOUNT_TYPE_CORPORATE");
                    break;
                case PRIVATE_CORPORATE_ACCOUNT:
                case PRIVATE_NON_CORPORATE_ACCOUNT:
                    bankAccountInfo.put("bank_account_type","BANK_ACCOUNT_TYPE_PERSONAL");
                    break;
                default:
            }
            bankAccountInfo.put("account_name",  wxPayCommonParamsHandle.rsaEncryptOAEP(merchantAccessDto.getMerchantAccessCard().getName(),publicKey));
            bankAccountInfo.put("account_bank",getAccountBank(merchantAccessDto.getMerchantAccessCard().getBankCode()));
            bankAccountInfo.put("bank_address_code",merchantAccessDto.getMerchantAccessCard().getAreaCode());
            bankAccountInfo.put("bank_branch_id",merchantAccessDto.getMerchantAccessCard().getBranchCode());
            bankAccountInfo.put("bank_name",merchantAccessDto.getMerchantAccessCard().getBankName());
            bankAccountInfo.put("account_number",  wxPayCommonParamsHandle.rsaEncryptOAEP(merchantAccessDto.getMerchantAccessCard().getCardNo(),publicKey));
            reqBody.put("bank_account_info",bankAccountInfo);

            log.info("微信提交进件 请求参数:{}", JsonUtils.toJsonString(reqBody));

            // 记录请求参数
            payChannelRequestDO.setRequestParams(JsonUtils.toJsonString(reqBody));
            payChannelRequestDO.setRequestUrl(Apply4SubApiEnum.APPLY_4_SUB.toString());
            payChannelRequestDO.setRequestTime(System.currentTimeMillis());

            // 请求
            IJPayHttpResponse response = WxPayApi.v3(
                    RequestMethodEnum.POST,
                    WxDomainEnum.CHINA.toString(),
                    Apply4SubApiEnum.APPLY_4_SUB.toString(),
                    wxPayConfig.getMchId(),
                    wxPayConfig.getSerialNo(),
                    wxPayConfig.getPayPublicId(),
                    wxPayConfig.getPrivateKeyPath(),
                    JSONUtil.toJsonStr(reqBody)
            );
            payChannelRequestDO.setResponse(response.getBody());
            log.info("微信提交进件 返回参数:{}", response);

            JSONObject resp = JSONUtil.parseObj(response.getBody());
            if(response.getStatus() != WxPayExtConstant.OK){
                channelMerchantAccessContext.setProcessStatus(false);
                channelMerchantAccessContext.setRemark(resp.getStr("message"));
                return;
            }
            merchantAccessInfo.setApplyNo(resp.getStr("applyment_id"));
            // 下一步就是查询申请状态
            channelMerchantAccessContext.setAccessStatus(MerchantEnum.ACCESS_STATUS.CHANNEL_APPROVE);

        }
        catch (Exception e) {
            log.error("微信开户请求失败,失败信息 message: {}", e.getMessage());
            channelMerchantAccessContext.setRemark("微信开户请求失败,失败信息" + (StringUtils.hasText(e.getMessage()) ? e.getMessage() : " 数据解析异常"));
            channelMerchantAccessContext.setProcessStatus(Boolean.FALSE);
            channelMerchantAccessContext.setAccessStatus(MerchantEnum.ACCESS_STATUS.APPROVE_REFUSE);
        }
    }

    @Override
    public String requestUrl(MerchantAccessDto merchantAccessInfoDO) {

        return null;
    }

    @Override
    public String channelParams(AccessChannelParamsDto accessChannelParamsDto) {
        WxAppChannelParams params = new WxAppChannelParams();
        params.setSubMchId(accessChannelParamsDto.getSubMchId());
        return JsonUtils.toJsonStringNotNull(params);
    }

    @Override
    public void merchantAccessQuery(ChannelMerchantAccessQueryContext channelMerchantAccessQueryContext) {

        log.info("微信查询进件 请求参数:{}", JsonUtils.toJsonString(channelMerchantAccessQueryContext));
        CommonResult<WxPayConfig> wxPayConfigCommonResult = wxPayCommonParamsHandle.wxPayConfig(channelMerchantAccessQueryContext.getProviderChannelConfig(),
                channelMerchantAccessQueryContext.isTest());
        if (!wxPayConfigCommonResult.isSuccess()) {
            channelMerchantAccessQueryContext.setRemark(wxPayConfigCommonResult.getMsg());
            channelMerchantAccessQueryContext.setProcessStatus(false);
            return;
        }
        // 进件信息
        MerchantAccessInfoDO merchantAccessInfo = channelMerchantAccessQueryContext.getMerchantAccessInfo();
        // 微信配置信息
        WxPayConfig wxPayConfig = wxPayConfigCommonResult.getData();

        try{
            // 微信支付分配的申请单号
            String applymentId = merchantAccessInfo.getApplyNo();
            if(StrUtil.isEmpty(applymentId)){
                channelMerchantAccessQueryContext.setRemark("微信查询进件 参数applyment_id is null");
                channelMerchantAccessQueryContext.setProcessStatus(false);
                return;
            }

            // 请求
            IJPayHttpResponse response = WxPayApi.v3(
                    RequestMethodEnum.GET,
                    WxDomainEnum.CHINA.toString(),
                    String.format(Apply4SubApiEnum.GET_APPLY_STATE_BY_ID.toString(), applymentId),
                    wxPayConfig.getMchId(),
                    wxPayConfig.getSerialNo(),
                    wxPayConfig.getPayPublicId(),
                    wxPayConfig.getPrivateKeyPath(),
                    ""
            );
            log.info("微信查询进件 返回参数:{}", response);
            if(response.getStatus() != WxPayExtConstant.OK){
                channelMerchantAccessQueryContext.setProcessStatus(false);
                channelMerchantAccessQueryContext.setRemark(response.getBody());
                return;
            }

            WxPayAccessQueryResp wxPayAccessQueryResp = JSONUtil.toBean(response.getBody(),WxPayAccessQueryResp.class);

            // 待签约会返回 特约商户号 和 商户链接
            if(StrUtil.isNotEmpty(wxPayAccessQueryResp.getSign_url())){
                MerchantAccessSignLink  signLink = new MerchantAccessSignLink();
                signLink.setLink(wxPayAccessQueryResp.getSign_url());
                channelMerchantAccessQueryContext.setSignLinks(CollUtil.newArrayList(signLink));
                merchantAccessInfo.setSubMchId(wxPayAccessQueryResp.getSub_mchid());
            }
            /**
             * 审核状态转换
             * 系统审核状态 0：草稿 1：鉴权中 2：已提交，等待平台审核，3：系统自动审核中，4：系统审核通过渠道审核中，5：平台审核中，6：待签约，7：签约中，8：待配置，9：配置中，10：审核完成，11：审核驳回
             * 微信进件审核状态如下：
             * APPLYMENT_STATE_EDITTING         编辑中  -> 审核驳回
             * APPLYMENT_STATE_AUDITING         审核中  -> 渠道审核
             * APPLYMENT_STATE_REJECTED         已驳回  -> 审核驳回
             * APPLYMENT_STATE_TO_BE_CONFIRMED  待账户验证 -> 待签约/签约中
             * APPLYMENT_STATE_TO_BE_SIGNED     待签约 -> 待签约
             * APPLYMENT_STATE_SIGNING          开通权限中 ->待配置
             * APPLYMENT_STATE_FINISHED         已完成 ->  审核完成
             * APPLYMENT_STATE_CANCELED         已作废 ->  审核驳回
             */
            switch (wxPayAccessQueryResp.getApplyment_state()) {
                // 审核驳回
                case "APPLYMENT_STATE_REJECTED":
                case "APPLYMENT_STATE_EDITTING":
                case "APPLYMENT_STATE_CANCELED":
                    channelMerchantAccessQueryContext.setProcessStatus(false);
                    channelMerchantAccessQueryContext.setAccessStatus(MerchantEnum.ACCESS_STATUS.APPROVE_REFUSE);
                    if(CollUtil.isNotEmpty(wxPayAccessQueryResp.getAudit_detail())){
                        channelMerchantAccessQueryContext.setRemark(JSONUtil.toJsonStr(wxPayAccessQueryResp.getAudit_detail()));
                    }
                    break;
                case "APPLYMENT_STATE_AUDITING":
                case "APPLYMENT_STATE_TO_BE_CONFIRMED":
                case "APPLYMENT_STATE_TO_BE_SIGNED":
                case "APPLYMENT_STATE_SIGNING":
                    // 重复查询流程
                    channelMerchantAccessQueryContext.setAccessStatus(MerchantEnum.ACCESS_STATUS.WAIT_SIGN);
                    channelMerchantAccessQueryContext.setAuditStatus(MerchantEnum.CHANNEL_CONFIG_STATUS.CONTINUE_APPLY_QUERY);
                    break;
                case "APPLYMENT_STATE_FINISHED":
                    channelMerchantAccessQueryContext.setAccessStatus(MerchantEnum.ACCESS_STATUS.APPROVE_SUCCESS);
                    channelMerchantAccessQueryContext.setAuditStatus(MerchantEnum.CHANNEL_CONFIG_STATUS.FINISH);
                    break;
                default:
                    channelMerchantAccessQueryContext.setProcessStatus(false);
                    channelMerchantAccessQueryContext.setRemark(response.getBody());
                    break;

            }

        }catch (Exception e){
            channelMerchantAccessQueryContext.setProcessStatus(false);
            channelMerchantAccessQueryContext.setRemark(e.getMessage());
        }
    }

    @Override
    public void merchantSign(ChannelMerchantAccessSignContext channelMerchantAccessSignContext) {
    }

    @Override
    public void merchantSignQuery(ChannelMerchantAccessSignContext channelMerchantAccessSignContext) {

    }

    @Override
    public void merchantBusinessOpen(ChannelMerchantBusinessContext channelMerchantBusinessContext) {


    }

    @Override
    public void wechatConfigInit(ChannelMerchantBusinessContext channelMerchantBusinessContext) {
    }

    @Override
    public void wechatConfigAdd(ChannelMerchantBusinessContext channelMerchantBusinessContext) {
    }

    @Override
    public void wechatConfigQuery(ChannelMerchantAccessAuthQueryContext channelMerchantAccessAuthQueryContext) {

    }

    @Override
    public void wechatAuthConfig(ChannelMerchantBusinessContext channelMerchantBusinessContext) {
    }

    @Override
    public boolean authConfigQueryType() {
        return true;
    }

    @Override
    public void wechatAuthQuery(ChannelMerchantAccessAuthQueryContext channelMerchantAccessAuthQueryContext) {
    }

    @Override
    public void alipayAuthConfig(ChannelMerchantBusinessContext channelMerchantBusinessContext) {
    }

    @Override
    public void alipayAuthQuery(ChannelMerchantAccessAuthQueryContext channelMerchantAccessAuthQueryContext) {
    }

    @Override
    public MerchantAccessCallBackDto accessCallBackParamsParse(HttpServletRequest request, ProviderChannelConfigDO providerChannelConfigDO) {
        Map<String, String[]> parameterMap = request.getParameterMap();
        MerchantAccessCallBackDto merchantAccessCallBackDto=new MerchantAccessCallBackDto();
        merchantAccessCallBackDto.setRequestId(parameterMap.get("external_agreement_no")[0]);
        merchantAccessCallBackDto.setSubMchId(parameterMap.get("agreement_no")[0]);
        merchantAccessCallBackDto.setAccessStatus(MerchantEnum.ACCESS_STATUS.WAIT_SET);
        return merchantAccessCallBackDto;
    }

    @Override
    public CommonResult<String> accessCallbackParse(String callBackBody, List<ProviderChannelConfigDO> channelConfigDOList) {
        return null;
    }

    @Override
    public MerchantBusinessCallBackDto businessCallBackParamsParse(String callBackBody, ProviderChannelConfigDO providerChannelConfigDO) {
        return FuYouCallBackParamsParseUtil.businessCallBackParamsParse(callBackBody);
    }

    @Override
    public boolean verify(String callBackBody, ProviderChannelConfigDO providerChannelConfigDO) {
        return false;
    }

    @Override
    public String callBackResponse(CommonResult commonResult) {
        if (commonResult.isSuccess()) {
            return "SUCCESS";
        }
        else {
            return "FAIL";
        }
    }

    @Override
    public void termAdd(ChannelMerchantTermContext channelMerchantTermContext) {

    }

    @Override
    public void reloadMerchantAuth(ChannelMerchantBusinessContext channelMerchantBusinessContext) {

    }

    @Override
    public void channelSplit(ChannelMerchantBusinessContext channelMerchantBusinessContext) {

    }

    @Override
    public void productUpdate(ChannelMerchantBusinessContext channelMerchantBusinessContext) {

    }

    @Override
    public Integer queryMerAuthStatus(ChannelMerchantAccessAuthQueryContext channelMerchantAccessAuthQueryContext) {
        return null;
    }

    @Override
    public MerchantProductQueryResp productQuery(ChannelMerchantBusinessContext channelMerchantBusinessContext) {
        return null;
    }

    @Override
    public MerchantChannelSplitCallBackDto easySplitCallBackParamsParse(HttpServletRequest request, ProviderChannelConfigDO providerChannelConfigDO) {
        return null;
    }




    /**
     * 获取受益人信息
     * @param uboInfoList
     * @return
     */
    private  JSONArray getUnoArray(List<MerchantAccessCertInfoDO> uboInfoList,WxPayConfig wxPayConfig,PublicKey publicKey) {
        JSONArray JSONArray = new JSONArray();
        try{
            if(CollUtil.isEmpty(uboInfoList)){
                return null;
            }
            for(MerchantAccessCertInfoDO uboInfo:uboInfoList){
                com.alibaba.fastjson.JSONObject dto = new com.alibaba.fastjson.JSONObject();
                // 受益人证件类型
                dto.put("ubo_id_doc_type", wxPayCommonParamsHandle.certType(uboInfo.getCertType()));
                // 证件正面照片
                dto.put("ubo_id_doc_copy", wxPayCommonParamsHandle.getV3UploadFileMediaId(uboInfo.getCertFrontUrl(),wxPayConfig));
                // 证件反面照片
                dto.put("ubo_id_doc_copy_back", wxPayCommonParamsHandle.getV3UploadFileMediaId(uboInfo.getCertBackUrl(),wxPayConfig));
                // 受益人名称
                dto.put("ubo_id_doc_name", wxPayCommonParamsHandle.rsaEncryptOAEP(uboInfo.getName(),publicKey));
                // 证件号码
                dto.put("ubo_id_doc_number", wxPayCommonParamsHandle.rsaEncryptOAEP(uboInfo.getCertNo(),publicKey));
                // 受益人证件地址
                dto.put("ubo_id_doc_address", wxPayCommonParamsHandle.rsaEncryptOAEP(uboInfo.getAddress(),publicKey));
                // 受益人证件有效期开始时间
                dto.put("ubo_period_begin", uboInfo.getCertBeginDate());
                if(uboInfo.getCertValidityType() == 1){
                    dto.put("ubo_period_end", "长期");
                }else{
                    // 受益人证件有效期结束时间
                    dto.put("ubo_period_end", uboInfo.getCertEndDate());
                }
                JSONArray.add(dto);
            }

        }catch (Exception e){
            throw new RuntimeException("wxpay getUnoArray 异常", e);
        }
        return JSONArray;
    }



    public String getAccountBank(String bankCode){
        PayChannelDictDO payChannelDictDO = payChannelDictService.queryChannelDict(MerchantExtConstant.CHANNEL_WX_PAY, PayEnums.DICT_KEY.BANK_CODE.getCode(),
                bankCode);
        if(payChannelDictDO != null){
            return payChannelDictDO.getDictDesc();
        }
        return null;
    }

    public static void main(String[] args) throws Exception {

        WxPayConfig wxPayConfig = new WxPayConfig();
        wxPayConfig.setMchId("702940067");
        wxPayConfig.setSerialNo("24FEAC0273A0EBF950B6CBDCFF70782CAAF541A2");
        wxPayConfig.setApiV3Key("48badc476a52825d1a408f87677ee770");
        wxPayConfig.setPrivateKeyPath("E:/work/local_file/secret/20250319/c2bbc2303d494dd7a95dc613aced9089_apiclient_key.pem");
        wxPayConfig.setPayPublicId("PUB_KEY_ID_0118000073852025031800396400002501");
        wxPayConfig.setPayPublicPath("E:/work/local_file/secret/20250319/292fccaaeebf4b6a8d71263b47491ebb_pub_key.pem");



        PrivateKey privateKey2 = PayKit.getPrivateKey(wxPayConfig.getPrivateKeyPath(), AuthTypeEnum.RSA.getCode());

        String name = "Jack";
        System.out.println("开始:"+name);


        // Map<String, String> keys = RsaKit.getKeys();
        // String certificate1 = (String)keys.get("certificate");
        // String privateKey1 = (String)keys.get("privateKey");
        // String content = "我是Javen,I am Javen";
        // String encrypt = RsaKit.encryptBycertificate(content, certificate1);
        // String decrypt = RsaKit.decryptByPrivateKey(encrypt, privateKey1);
        // System.out.println("加密之后：" + encrypt);
        // System.out.println("解密之后：" + decrypt);
        // System.out.println("======华丽的分割线=========");
        // content = "我是Javen,I am Javen";
        // encrypt = PayKit.rsaEncryptOAEP(content, certificate1);
        // decrypt = RsaKit.decryptByPrivateKeyByWx(encrypt, privateKey1);
        // System.out.println("加密之后：" + encrypt);
        // System.out.println("解密之后：" + decrypt);
        // String sign = RsaKit.encryptByPrivateKey(content, privateKey1);
        // System.out.println("加密之后：" + sign);

        //
        // wxPayConfig.setMchId("702940067");
        // wxPayConfig.setSerialNo("1F8721F0F9A8DC630E718FA23E2D4CD71B352207");
        // wxPayConfig.setApiV3Key("48badc476a52825d1a408f87677ee770");
        // wxPayConfig.setcertificatePath("C:\\Users\\Administrator\\Documents\\WXWork\\1688855412705752\\Cache\\File\\2025-03\\702940067_20250318_cert(1)\\apiclient_cert.pem");
        // wxPayConfig.setPlatformCertPath("C:\\Users\\Administrator\\Documents\\WXWork\\1688855412705752\\Cache\\File\\2025-03\\702940067_20250318_cert(1)\\111_wx_cert.pem");
        // wxPayConfig.setPrivateKeyPath("C:\\Users\\Administrator\\Documents\\WXWork\\1688855412705752\\Cache\\File\\2025-03\\702940067_20250318_cert(1)\\apiclient_key.pem");
        String img = "E:/cert/gift_8.png";


        // Map<String,Object> params = new HashMap<>();
        // params.put("limit",10);
        // params.put("offset",0);
        //
        // String url = String.format(ComplaintsApiEnum.COMPLAINTS_NEGOTIATION_HISTORY.toString()+"?"+URLUtil.buildQuery(params,null),"200000020250303110255410899");
        // IJPayHttpResponse response = WxPayApi.v3(
        //         RequestMethodEnum.GET,
        //         WxDomainEnum.CHINA.toString(),
        //         url ,
        //         wxPayConfig.getMchId(),
        //         wxPayConfig.getSerialNo(),
        //         getPlatSerialNumber(wxPayConfig),
        //         wxPayConfig.getPrivateKeyPath(),
        //         "",
        //         AuthTypeEnum.RSA.getCode()
        // );


        String subAppid = "wx264bba4e9b29efe8";
        String prepay_id = "wx201410272009395522657a690389285100";
        // Map<String,String> prepayReqMap = WxPayKit.jsApiCreateSign(subAppid,prepay_id,wxPayConfig.getPrivateKeyPath());

        // Map<String,String> prepayReqMap = WxPayKit.appCreateSign(subAppid,wxPayConfig.getMchId(),prepay_id,wxPayConfig.getPrivateKeyPath());
        // System.out.println(JSONUtil.toJsonPrettyStr(prepayReqMap));

        // String ss = "719餐饮";
        // System.out.println(ss.substring(0,3));
        // System.out.println(ss.substring(3,ss.length()));
//        String appNo = String.format(Apply4SubApiEnum.GET_APPLY_STATE_BY_ID.toString(), "2000002612569349");
//        // 请求
//         X509Certificate certificate = PayKit.getCertificate(FileUtil.getInputStream(wxPayConfig.getPlatformCertPath()));
//         String platSerialNo = certificate.getSerialNumber().toString(16).toUpperCase();
//         String mediaIdUrl = "/v3/merchant-service/images/ChsyMDAwMDAwMjAyNTAzMDMxMTAyNTU0MTA4OTkYACDv6rq%2BBigBMAE4AQ%3D%3D";

        // String auth = WxPayKit.buildAuthorization(RequestMethodEnum.GET,mediaIdUrl,wxPayConfig.getMchId(),wxPayConfig.getSerialNo(),wxPayConfig.getPrivateKeyPath(),"");
        // log.info("微信查询图片 返回参数:{}", auth);
        // 初始化文件上传服务

        // Map<String,String>  headers = new HashMap<>();
        //
        // headers.put("Authorization",auth);
        // headers.put("Accept","application/json");
        // HttpRequest request = HttpUtil.createGet("https://api.mch.weixin.qq.com/v3/merchant-service/images/ChsyMDAwMDAwMjAyNTAzMDMxMTAyNTU0MTA4OTkYACDv6rq%2BBigBMAE4AQ%3D%3D").headerMap(headers,false);
        // HttpResponse response = request.execute();
        // File file = new File("E:/work/local_file/secret/20250307/image5.png");
        // response.writeBody(file);
        //
        // FileUtil.createTempFile(".png",true);
       //  IJPayHttpResponse response1 = WxPayApi.v3(
       //          RequestMethodEnum.GET,
       //          WxDomainEnum.CHINA.toString(),
       //          "/v3/merchant-service/images/ChsyMDAwMDAwMjAyNTAzMDMxMTAyNTU0MTA4OTkYACDv6rq%2BBigBMAE4AQ%3D%3D",
       //          wxPayConfig.getMchId(),
       //          wxPayConfig.getSerialNo(),
       //          null,
       //          wxPayConfig.getPrivateKeyPath(),
       //          "",
       //          AuthTypeEnum.RSA.getCode()
       //  );
       //  byte[] binaryData1 = response1.getBody().getBytes();
       //  // 处理二进制流数据的逻辑代码
       //  try (OutputStream outputStream = new FileOutputStream("E:/work/local_file/secret/20250307/image3.jpg")) {
       //      outputStream.write(binaryData1);
       //  } catch (IOException e) {
       //      // 处理保存文件异常的逻辑代码
       //  }
       //  https://blog.51cto.com/u_16213344/9328040
       // log.info("微信查询图片 返回参数:{}", response1);
       //  JSONObject jsonObject = JSONUtil.parseObj(response.getBody());
       // String imgByte = jsonObject.getStr("chunk");
       //  log.info("微信查询图片流 返回参数:{}", imgByte);
//
//        WxPayAccessQueryResp wxPayAccessQueryResp = JSONUtil.toBean(response.getBody(),WxPayAccessQueryResp.class);
//
//        System.out.println(JSONUtil.toJsonStr(response));

//        X509Certificate Platformcertificate = PayKit.getCertificate(FileUtil.getInputStream(wxPayConfig.getPlatformCertPath()));
//        String platSerialNo = Platformcertificate.getSerialNumber().toString(16).toUpperCase();
//        System.out.println(platSerialNo);
//        String upload = getV3UploadFileMediaId("https://img.hbhlpay.com/image/20250225/8b27577a-09e5-4783-a45f-aa6b155352d6.jpg",wxPayConfig);
//
////        String upload = getV3UploadFileMediaId("E:/work/local_file/secret/20250220/4deb2c33-fd7b-4202-8b8f-38911ba89821.png",wxPayConfig);
//        System.out.println(upload);


//        // 敏感信息加密
//        X509Certificate publiccertificate = PayKit.getCertificate(FileUtil.getInputStream(wxPayConfig.getPlatformCertPath()));
//        String name = "Jack";
//        System.out.println(name);
//        String enName = PayKit.rsaEncryptOAEP(name,publiccertificate);
//        System.out.println("密码后:"+enName);
//        PrivateKey privateKey = PayKit.getPrivateKey(wxPayConfig.getPrivateKeyPath(), AuthTypeEnum.RSA.getCode());
//        System.out.println("解密后:"+PayKit.rsaDecryptOAEP(enName,privateKey));



        // 获取平台证书列表
       // try {
       //     IJPayHttpResponse response = WxPayApi.v3(
       //             RequestMethodEnum.GET,
       //             WxDomainEnum.CHINA.toString(),
       //             OtherApiEnum.GET_CERTIFICATES.getUrl(),
       //             wxPayConfig.getMchId(),
       //             wxPayConfig.getSerialNo(),
       //             null,
       //             wxPayConfig.getPrivateKeyPath(),
       //             "",
       //             AuthTypeEnum.RSA.getCode()
       //     );
       //     Map<String, List<String>> headers = response.getHeaders();
       //     log.info("请求头: {}", headers);
       //     String serialNumber = response.getHeader("Wechatpay-Serial");
       //
       //     String body = response.getBody();
       //     int status = response.getStatus();
       //
       //     log.info("serialNumber: {}", serialNumber);
       //     log.info("status: {}", status);
       //     log.info("body: {}", body);
       //     int isOk = 200;
       //     if (status == isOk) {
       //         JSONObject jsonObject = JSONUtil.parseObj(body);
       //         cn.hutool.json.JSONArray dataArray = jsonObject.getJSONArray("data");
       //         // 默认认为只有一个平台证书
       //         JSONObject encryptObject = dataArray.getJSONObject(0);
       //         JSONObject encryptCertificate = encryptObject.getJSONObject("encrypt_certificate");
       //         String associatedData = encryptCertificate.getStr("associated_data");
       //         String cipherText = encryptCertificate.getStr("ciphertext");
       //         String nonce = encryptCertificate.getStr("nonce");
       //         String algorithm = encryptCertificate.getStr("algorithm");
       //         String serialNo = encryptObject.getStr("serial_no");
       //         // 根据证书序列号查询对应的证书来验证签名结果
       //         final String platSerialNo = savePlatformCert(associatedData, nonce, cipherText, algorithm, wxPayConfig.getPlatformCertPath(),wxPayConfig.getApiV3Key());
       //         log.info("平台证书序列号: {} serialNo: {}", platSerialNo, serialNo);
       //     }
       // } catch (Exception e) {
       //     log.error("获取平台证书列表异常", e);
       // }


    }


    /**
     * 获取平台证书序列号
     * @return
     */

    // private static String savePlatformCert(String associatedData, String nonce, String cipherText, String algorithm, String certPath,String  key3) {
    //     try {
    //         String certificate;
    //         if (StrUtil.equals(algorithm, AuthTypeEnum.SM2.getPlatformCertAlgorithm())) {
    //             certificate = PayKit.sm4DecryptToString(key3, cipherText, nonce, associatedData);
    //         } else {
    //             AesUtil aesUtil = new AesUtil(key3.getBytes(StandardCharsets.UTF_8));
    //             // 平台证书密文解密
    //             // encrypt_certificate 中的  associated_data nonce  ciphertext
    //             certificate = aesUtil.decryptToString(
    //                     associatedData.getBytes(StandardCharsets.UTF_8),
    //                     nonce.getBytes(StandardCharsets.UTF_8),
    //                     cipherText
    //             );
    //         }
    //         if (StrUtil.isNotEmpty(certificate)) {
    //             // 保存证书
    //             FileWriter writer = new FileWriter(certPath);
    //             writer.write(certificate);
    //             // 获取平台证书序列号
    //             X509Certificate certificate = PayKit.getCertificate(new ByteArrayInputStream(certificate.getBytes()));
    //             return certificate.getSerialNumber().toString(16).toUpperCase();
    //         }
    //         return "";
    //     } catch (Exception e) {
    //         log.error("保存平台证书异常", e);
    //         return e.getMessage();
    //     }
    // }

}
